#include "sk_game_model.h"
#include "sk_game_item.h"
#include "sk_swap.h"

#include <QDebug>
#include <QStack>

namespace sk
{

GameModel::GameModel(QObject * parent)
    :
QAbstractItemModel(parent)
{
    _rootItem = 0;
}

GameModel::~GameModel()
{
    reload(0);
}

void GameModel::reload(GameItem * rootItem)
{
    if (_rootItem)
    {
        delete _rootItem;
        _rootItem = 0;
    }
    Q_ASSERT(0 == _rootItem);
    _rootItem = rootItem;
}

QModelIndex GameModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
{
    // qDebug() << "index" << row << column << "parent: " << parent.row() << parent.column();
    if (0 == _rootItem)
    {
        return QModelIndex();
    }

    if (!hasIndex(row, column, parent))
    {
        return QModelIndex();
    }

    GameItem * item = getItem(parent);
    GameItem * childItem = item->child(row);

    if (childItem)
    {
        return createIndex(row, column, childItem);
    }
    else
    {
        return QModelIndex();
    }
}

QModelIndex GameModel::parent(const QModelIndex &child) const
{
    // qDebug() << "parent" << child.row() << child.column();
    if (0 == _rootItem || !child.isValid())
    {
        return QModelIndex();
    }

    GameItem * childItem = static_cast<GameItem*>(child.internalPointer());
    GameItem * parentItem = childItem->parent();

    if (!parentItem || parentItem == _rootItem)
    {
        return QModelIndex();
    }
    return createIndex(parentItem->index(), 0, parentItem);

}

GameItem * GameModel::getItem(const QModelIndex &index) const
{
    if (!index.isValid())
    {
        return _rootItem;
    }
	QStack<int> s;
	QModelIndex idx = index;
	while(idx.isValid())
	{
		s.push(idx.row());
		idx = idx.parent();
	}
	GameItem * res = _rootItem;
	while (!s.isEmpty())
	{
		res = res->child(s.pop());
	}
	return res;

    //return static_cast<GameItem*>(index.internalPointer());
}

int GameModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const
{
    // qDebug() << "rowCount" << parent.row() << parent.column();
    if (0 == _rootItem)
    {
        return 0;
    }

    if (parent.row() == -1 && parent.column() == -1) // root element
    {
        //qDebug() << "return 1";
        return 1;
    }

    GameItem * item = getItem(parent);
    return item->numChilds();
}

int GameModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const
{
    // qDebug() << "columnCount" << parent.row() << parent.column();
    if (0 == _rootItem)
    {
        return 0;
    }
    return 1;
}


QVariant GameModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
{
    // qDebug() << "data" << index.row() << index.column() << role;
    if (0 == _rootItem)
    {
        return QVariant();
    }
    if (role == Qt::DisplayRole)
    {
        return QString::number((qlonglong)getItem(index));
    }
    return QVariant();
}

QModelIndex GameModel::getParentIndex(const QVector<int>& _index)
{
    QModelIndex p = QModelIndex();
    QModelIndex s = QModelIndex();
    for (int i = 0; i < _index.size(); ++i)
    {
        if (i > 0) p = s;
        s = index(_index[i], 0, p);
    }
    return p;
}

QModelIndex GameModel::getIndex(const QVector<int>& _index)
{
    return index(_index.back(), 0, getParentIndex(_index));
}

GameItem * GameModel::create(GameItem * parent, void * param)
{
	QModelIndex p = getIndex(parent->getIndex());
	beginInsertRows(p, parent->numChilds(), parent->numChilds());
	GameItem * res = parent->createItem(param);
	endInsertRows();
	return res;
}

void GameModel::remove(GameItem * item)
{
	QVector<int> _index = item->getIndex();
    if (_index.size() == 0)
    {
        return;
    }
    QModelIndex p = getParentIndex(_index);
    beginRemoveRows(p, _index.back(), _index.back());
	item->doDelete();
    endRemoveRows();
}

void GameModel::onSwapItems(GameItem * parent, int i, int j)
{
	if (i > j)
	{
            sk::swap(i, j);
	}
	QModelIndex p = getIndex(parent);
	QModelIndex ii = index(i, 0, p);
	QModelIndex jj = index(j, 0, p);
	emit dataChanged(ii, jj);
	//emit dataChanged(jj, jj);
}

QModelIndex GameModel::getIndex(GameItem * item)
{
    return getIndex(item->getIndex());
}



} // namespace sk
